package com.wiwf.model.security.service.impl;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.wiwf.model.bean.SysUserVoto;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.ObjectUtils;

import com.wiwf.model.security.service.SysTokenService;

/**
 * @author kehui
 */
@Service
public class SysTokenServiceImpl implements SysTokenService {

	@Resource
	private RedisTemplate<String, SysUserVoto> redisTemplate;
	
	@Value("${base.security.tokenkey:token}")
	private String tokenKey;

	@Value("${base.security.tokentime:31200}")
	private Integer tokenTime;

	private String nextToken;

	@Override
	public String createToken() {
		String token = UUID.randomUUID().toString();
		this.nextToken = getTagString(token);
		return this.nextToken;
	}

	@Override
	public Boolean addTokenUser(HttpServletResponse response, String key, SysUserVoto val) {
		// token 写入 cookie
		Cookie cookie = new Cookie(tokenKey, key);
		cookie.setPath("/");
		response.addCookie(cookie);
		
		// data 写入 redis
		redisTemplate.opsForValue().set(key, val, tokenTime, TimeUnit.SECONDS);

		return true;
	}

	@Override
	public Boolean updateTokenUser(HttpServletResponse response, HttpServletRequest request, String key, SysUserVoto val) {
		delTokenUser(request);
		addTokenUser(response, key, val);
		return true;
	}

	@Override
	public SysUserVoto getTokenUser(HttpServletResponse response, HttpServletRequest request) {
		String token = getToken(request);
		SysUserVoto user = new SysUserVoto();
		if(ObjectUtils.isEmpty(token)) {
			 return user;
		}
		user = redisTemplate.opsForValue().get(token);
		if(ObjectUtils.isEmpty(user)) {
			return user;
		} else {
			addTokenUser(response, token, user);
		}
		return user;
	}

	@Override
	public SysUserVoto getTokenUser(String token) {
		return redisTemplate.opsForValue().get(token);
	}
	
	@Override
	public Boolean delTokenUser(HttpServletRequest request){
		String token = getToken(request);
		return delTokenUser(token);
	}
	@Override
	public Boolean delTokenUser(String token) {
		if(! ObjectUtils.isEmpty(token)) {
			return redisTemplate.delete(token);
		}
		return false;
	}

	@Override
	public Boolean updateTokenUserExpire(String key) {
		try {
			redisTemplate.expire(key, tokenTime, TimeUnit.SECONDS);
		} catch (Exception e) {
			return true;
		}
		return true;
	}
	
	@Override
	public void delToken(HttpServletResponse response) {
		Cookie cookieToken = new Cookie(tokenKey, "");
		cookieToken.setPath("/");
		cookieToken.setMaxAge(0);
		response.addCookie(cookieToken);
		response.setHeader("Set-Cookie", tokenKey + "=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0");
	}
	
	@Override
	public String getToken(HttpServletRequest request) {
		if(! ObjectUtils.isEmpty(this.nextToken)) {
			String token = this.nextToken;
			this.nextToken = null;
			return token;
		}
		try {
			Cookie[] cookies = request.getCookies();
			if(cookies == null || cookies.length == 0){
				return request.getHeader(tokenKey);
			}
			for (Cookie cookie : cookies) {
				if(cookie.getName().equals(tokenKey)) {
					return cookie.getValue();
				}
			}
		} catch (Exception e) {
			return null;
		}
		return request.getHeader(tokenKey);
	}

	String getTagString(String tag) {
		try {
			byte md5[] = MessageDigest.getInstance("md5").digest(tag.getBytes());

			return Base64Utils.encodeToString(Base64Utils.encode(md5));
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public String getTokenKey() {
		return this.tokenKey;
	}

}
